#include "EvaluatorFunctions.h"

int ScoreRow(int _startX, int _startY, CoordinateGetter &_coordGet, GomokuBoard &_board, int _player) {
	int t_totalCount = 0;

	bool t_openBegin = false;
	int t_length = 0;

	int t_curVal;
	int t_lastVal;

	bool t_curGoodCoords = true;
	bool t_lastGoodCoords = true;

	for(int offset = 0; t_curGoodCoords; offset++) {
		int t_x, t_y;
		bool t_xGood, t_yGood;
		t_x = _coordGet.GetX(_startX, _startY, offset);
		t_xGood = t_x >= 0 && t_x < 19;
		t_y = _coordGet.GetY(_startX, _startY, offset);
		t_yGood = t_y >= 0 && t_y < 19;
		t_curGoodCoords = t_xGood && t_yGood;
		t_curVal = _board.Get(t_x, t_y);

		t_x = _coordGet.GetX(_startX, _startY, offset-1);
		t_xGood = t_x >= 0 && t_x < 19;
		t_y = _coordGet.GetY(_startX, _startY, offset-1);
		t_yGood = t_y >= 0 && t_y < 19;
		t_lastGoodCoords = t_xGood && t_yGood;
		t_lastVal = _board.Get(t_x, t_y);

		if(t_length == 0 && t_curVal == _player) { //row start
			t_openBegin = t_lastGoodCoords && t_lastVal == 0;
			t_length = 1;
		}
		else if(t_curVal == _player) { //row continue
			t_length++;
		}
		else if(t_length != 0) { //row end
			bool t_openEnd = t_curGoodCoords && t_curVal == 0;
			
			if(t_openBegin && t_openEnd)
				t_totalCount += unBoundRowWeight[t_length-1]; //open both sides
			else if(t_openBegin || t_openEnd)
				t_totalCount += boundRowWeight[t_length-1]; //open on one side

			t_length = 0;
			t_openBegin = false;
		}
	}
	return t_totalCount;
}

int OneSidedSimpleHeuristic(GomokuBoard &_board, int _player) {
	int t_heuristicValue = 0;

	//horizontal rows
	HorizontalGetter hgetter;
	for(int y = 0; y <= boardHeight; y++) {
		t_heuristicValue += ScoreRow(0, y, hgetter, _board, _player);
	}

	//vertical rows
	VerticalGetter vgetter;
	for(int x = 0; x <= boardWidth; x++) {
		t_heuristicValue += ScoreRow(x, 0, vgetter, _board, _player);
	}

	//Up To Down Diagonal rows
	UpToDownDiagonalGetter uddgetter;
	for(int y = 0; y <= boardHeight; y++) {
		t_heuristicValue += ScoreRow(0, y, uddgetter, _board, _player);
	}
	for(int x = 1; x <= boardWidth; x++) {
		t_heuristicValue += ScoreRow(x, 0, uddgetter, _board, _player);
	}

	//Down To Up Diagonal rows
	DownToUpDiagonalGetter dudgetter;
	for(int y = 0; y <= boardHeight; y++) {
		t_heuristicValue += ScoreRow(0, y, dudgetter, _board, _player);
	}
	for(int x = 1; x <= boardWidth; x++) {
		t_heuristicValue += ScoreRow(x, 0, dudgetter, _board, _player);
	}
	return t_heuristicValue;
}

int SimpleHeuristic(GomokuBoard &_board, int _player) {
	return OneSidedSimpleHeuristic(_board, _player);
}

int ThreatHeuristic(GomokuBoard &board, int player)
{
	int t_opponent = 1;
	if(player == 1) t_opponent = 2;

	int t_heuristicValue = 0;
	Board t_board;
	std::list<Threat> t_threats;

	for(int a = 0; a < 19; a++) for(int b = 0; b < 19; b++) t_board[a][b] = board.Get(a, b);

	FindAllThreats(player, t_board, t_threats);

	for(std::list<Threat>::iterator it = t_threats.begin(); it != t_threats.end(); it++)
	{
		switch((*it).m_type)
		{
		case THREAT_FIVE:
			t_heuristicValue += 4;
		break;

		case THREAT_FOUR_STRAIGHT:
			t_heuristicValue += 4;
		break;

		case THREAT_FOUR:
			t_heuristicValue += 3;
		break;

		case THREAT_THREE:
			t_heuristicValue += 2;
		break;
		}
	}

	return t_heuristicValue;
}